package org.ehe.erp.service.stock.imp;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.ehe.common.core.exception.ServiceException;
import org.ehe.common.mybatis.core.page.PageQuery;
import org.ehe.common.mybatis.core.page.TableDataInfo;
import org.ehe.erp.domain.stock.ErpStockCheck;
import org.ehe.erp.domain.stock.bo.ErpStockCheckBo;
import org.ehe.erp.domain.stock.vo.ErpStockCheckVo;
import org.ehe.erp.enums.stock.ErpStockCheckStatusEnum;
import org.ehe.erp.mapper.stock.ErpStockCheckMapper;
import org.ehe.erp.service.stock.IErpStockCheckService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.Date;
import java.util.List;

/**
 * @author :zhangnn
 * @className :ErpStockCheckServiceImpl
 * @description: TODO
 * @date 2025-08-28 17:36:29
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ErpStockCheckServiceImpl extends ServiceImpl<ErpStockCheckMapper, ErpStockCheck> implements IErpStockCheckService {
    private final ErpStockCheckMapper baseMapper;

    @Override
    public ErpStockCheckVo queryById(Long id) {
        ErpStockCheckVo vo = baseMapper.selectVoById(id);
        if (vo != null) {
            vo.setStatusName(ErpStockCheckStatusEnum.getNameByCode(vo.getStatus()));
        }
        return vo;
    }

    @Override
    public List<ErpStockCheckVo> queryList(ErpStockCheckBo bo) {
        LambdaQueryWrapper<ErpStockCheck> lqw = buildQueryWrapper(bo);
        List<ErpStockCheckVo> list = baseMapper.selectStockCheckList(lqw);
        list.forEach(vo -> vo.setStatusName(ErpStockCheckStatusEnum.getNameByCode(vo.getStatus())));
        return list;
    }

    @Override
    public TableDataInfo<ErpStockCheckVo> queryPageList(ErpStockCheckBo bo, PageQuery page) {
        LambdaQueryWrapper<ErpStockCheck> lqw = buildQueryWrapper(bo);
        //Page<ErpStockCheckVo> result = baseMapper.selectStockCheckPage(page, lqw);
        IPage<ErpStockCheckVo> erpStockCheckVoIPage = this.baseMapper.selectVoPage(page.build(), lqw);
        erpStockCheckVoIPage.getRecords().forEach(vo -> vo.setStatusName(ErpStockCheckStatusEnum.getNameByCode(vo.getStatus())));
        return TableDataInfo.build(erpStockCheckVoIPage);
    }

    private LambdaQueryWrapper<ErpStockCheck> buildQueryWrapper(ErpStockCheckBo bo) {
        LambdaQueryWrapper<ErpStockCheck> lqw = new LambdaQueryWrapper<>();
        lqw.like(StringUtils.isNotBlank(bo.getSearchNo()), ErpStockCheck::getNo, bo.getSearchNo());
        lqw.eq(bo.getStatus() != null, ErpStockCheck::getStatus, bo.getStatus());
        lqw.in(bo.getStatusList() != null && bo.getStatusList().length > 0, ErpStockCheck::getStatus, bo.getStatusList());
        lqw.ge(bo.getCheckStartTime() != null, ErpStockCheck::getCheckTime, bo.getCheckStartTime());
        lqw.le(bo.getCheckEndTime() != null, ErpStockCheck::getCheckTime, bo.getCheckEndTime());
        lqw.ge(bo.getMinPrice() != null, ErpStockCheck::getTotalPrice, bo.getMinPrice());
        lqw.le(bo.getMaxPrice() != null, ErpStockCheck::getTotalPrice, bo.getMaxPrice());
        lqw.eq(bo.getCreateDept() != null, ErpStockCheck::getCreateDept, bo.getCreateDept());
        lqw.eq(StringUtils.isNotBlank(bo.getTenantId()), ErpStockCheck::getTenantId, bo.getTenantId());
        lqw.orderByDesc(ErpStockCheck::getCreateTime);
        return lqw;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertByBo(ErpStockCheckBo bo) {
        ErpStockCheck add = BeanUtil.toBean(bo, ErpStockCheck.class);
        validEntityBeforeSave(add);

        // 如果没有指定单号，自动生成
        if (StringUtils.isBlank(add.getNo())) {
            add.setNo(generateCheckNo());
        }

        // 默认状态为草稿
        if (add.getStatus() == null) {
            add.setStatus(ErpStockCheckStatusEnum.DRAFT.getCode());
        }

        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByBo(ErpStockCheckBo bo) {
        ErpStockCheck update = BeanUtil.toBean(bo, ErpStockCheck.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(ErpStockCheck entity) {
        // 校验盘点单号是否已存在
        if (StringUtils.isNotBlank(entity.getNo())) {
            ErpStockCheck existCheck = baseMapper.selectByNo(entity.getNo());
            if (existCheck != null && !existCheck.getId().equals(entity.getId())) {
                throw new ServiceException("盘点单号已存在：" + entity.getNo());
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            // 校验是否可以删除
            for (Long id : ids) {
                ErpStockCheck check = baseMapper.selectById(id);
                if (check != null && !ErpStockCheckStatusEnum.DRAFT.getCode().equals(check.getStatus())) {
                    throw new ServiceException("只能删除草稿状态的盘点单");
                }
            }
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public ErpStockCheckVo queryByNo(String no) {
        ErpStockCheck check = baseMapper.selectByNo(no);
        if (check != null) {
            ErpStockCheckVo vo = BeanUtil.toBean(check, ErpStockCheckVo.class);
            vo.setStatusName(ErpStockCheckStatusEnum.getNameByCode(vo.getStatus()));
            return vo;
        }
        return null;
    }

    @Override
    public String generateCheckNo() {
        String dateStr = DateUtil.format(new Date(), "yyyyMMdd");
        String prefix = "PD";
        return baseMapper.generateCheckNo(prefix, dateStr);
    }

    @Override
    public Boolean isUniqueNo(ErpStockCheckBo bo) {
        ErpStockCheck check = baseMapper.selectByNo(bo.getNo());
        return check == null || check.getId().equals(bo.getId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean startCheck(Long id) {
        ErpStockCheck check = baseMapper.selectById(id);
        if (check == null) {
            throw new ServiceException("盘点单不存在");
        }

        if (!ErpStockCheckStatusEnum.DRAFT.getCode().equals(check.getStatus())) {
            throw new ServiceException("只有草稿状态的盘点单才能开始盘点");
        }

        check.setStatus(ErpStockCheckStatusEnum.IN_PROGRESS.getCode());
        return baseMapper.updateById(check) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean completeCheck(Long id) {
        ErpStockCheck check = baseMapper.selectById(id);
        if (check == null) {
            throw new ServiceException("盘点单不存在");
        }

        if (!ErpStockCheckStatusEnum.IN_PROGRESS.getCode().equals(check.getStatus())) {
            throw new ServiceException("只有盘点中状态的盘点单才能完成");
        }

        check.setStatus(ErpStockCheckStatusEnum.COMPLETED.getCode());
        return baseMapper.updateById(check) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean cancelCheck(Long id) {
        ErpStockCheck check = baseMapper.selectById(id);
        if (check == null) {
            throw new ServiceException("盘点单不存在");
        }

        if (ErpStockCheckStatusEnum.COMPLETED.getCode().equals(check.getStatus())) {
            throw new ServiceException("已完成的盘点单不能取消");
        }

        check.setStatus(ErpStockCheckStatusEnum.CANCELLED.getCode());
        return baseMapper.updateById(check) > 0;
    }

    @Override
    public List<ErpStockCheckVo> queryCheckStatusStats() {
        return baseMapper.selectCheckStatusStats(null);
    }

    @Override
    public List<ErpStockCheckVo> queryByStatus(Integer status) {
        List<ErpStockCheckVo> list = baseMapper.selectByStatus(status, null);
        list.forEach(vo -> vo.setStatusName(ErpStockCheckStatusEnum.getNameByCode(vo.getStatus())));
        return list;
    }
}
